home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-02-15 | 15.7 KB | 617 lines | [TEXT/CWIE] |
- ///--------------------------------------------------------------------------------------
- // SpriteLayer.c
- //
- // Portions are copyright: © 1991-94 Tony Myles, All rights reserved worldwide.
- //
- // Description: implementation of the sprite layers
- ///--------------------------------------------------------------------------------------
-
-
- #ifndef __SWCOMMON__
- #include "SWCommonHeaders.h"
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __SPRITEWORLDUTILS__
- #include "SpriteWorldUtils.h"
- #endif
-
- #ifndef __SPRITEWORLD__
- #include "SpriteWorld.h"
- #endif
-
- #ifndef __SPRITELAYER__
- #include "SpriteLayer.h"
- #endif
-
- #ifndef __SPRITE__
- #include "Sprite.h"
- #endif
-
-
-
- ///--------------------------------------------------------------------------------------
- // SWCreateSpriteLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC OSErr SWCreateSpriteLayer(
- SpriteLayerPtr *spriteLayerP)
- {
- OSErr err;
- SpriteLayerPtr tempSpriteLayerP;
-
- err = noErr;
- *spriteLayerP = NULL;
-
- tempSpriteLayerP = (SpriteLayerPtr)NewPtrClear((Size)sizeof(SpriteLayerRec));
-
- if (tempSpriteLayerP != NULL)
- {
- tempSpriteLayerP->tileLayer = 10;
- tempSpriteLayerP->isPaused = false;
-
- *spriteLayerP = tempSpriteLayerP;
- }
- else
- {
- err = MemError();
- }
-
- SWSetStickyIfError( err );
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWDisposeSpriteLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWDisposeSpriteLayer(
- SpriteLayerPtr *spriteLayerPP)
- {
- SpriteLayerPtr spriteLayerP = *spriteLayerPP;
-
- if (spriteLayerP != NULL)
- {
- DisposePtr((Ptr)spriteLayerP);
- *spriteLayerPP = NULL;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWAddSprite
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC OSErr SWAddSprite(
- SpriteLayerPtr spriteLayerP,
- SpritePtr newSpriteP)
- {
- SpritePtr tailSpriteP = spriteLayerP->tailSpriteP;
- OSErr err = noErr;
-
- SW_ASSERT(spriteLayerP != NULL);
- SW_ASSERT(newSpriteP != NULL);
-
- if (newSpriteP->parentSpriteLayerP != NULL)
- err = kSpriteAlreadyInLayer;
-
- if (err == noErr)
- {
- // attach the new sprite to the end of the list
- // or make it the head if the list is empty.
- if (tailSpriteP != NULL)
- tailSpriteP->nextSpriteP = newSpriteP;
- else
- spriteLayerP->headSpriteP = newSpriteP;
-
- // link up the new sprite in both directions
- newSpriteP->prevSpriteP = tailSpriteP;
- newSpriteP->nextSpriteP = NULL;
-
- // make the new sprite the tail
- spriteLayerP->tailSpriteP = newSpriteP;
-
- // mark the sprite to be drawn, in case the sprite changed tile layers
- newSpriteP->needsToBeDrawn = true;
-
- // Store the parentSpriteLayer in the Sprite
- newSpriteP->parentSpriteLayerP = spriteLayerP;
- }
-
- SWSetStickyIfError( err );
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWRemoveSprite
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC OSErr SWRemoveSprite(
- SpritePtr oldSpriteP)
- {
- SpriteLayerPtr spriteLayerP;
- OSErr err = noErr;
-
- SW_ASSERT(oldSpriteP != NULL);
-
- spriteLayerP = oldSpriteP->parentSpriteLayerP;
- if (spriteLayerP == NULL)
- err = kBadParameterErr;
-
- if (err == noErr)
- {
- // is this not the tail sprite?
- if (oldSpriteP->nextSpriteP != NULL)
- {
- // link the next sprite to the prev sprite
- oldSpriteP->nextSpriteP->prevSpriteP = oldSpriteP->prevSpriteP;
- }
- else
- {
- // make the prev sprite the tail
- spriteLayerP->tailSpriteP = oldSpriteP->prevSpriteP;
- }
-
- // is this not the head sprite?
- if (oldSpriteP->prevSpriteP != NULL)
- {
- // link the prev sprite to the next sprite
- oldSpriteP->prevSpriteP->nextSpriteP = oldSpriteP->nextSpriteP;
- }
- else
- {
- // make the next sprite the first sprite
- spriteLayerP->headSpriteP = oldSpriteP->nextSpriteP;
- }
-
- oldSpriteP->parentSpriteLayerP = NULL;
- }
-
- SWSetStickyIfError( err );
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWRemoveAllSpritesFromLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWRemoveAllSpritesFromLayer(
- SpriteLayerPtr srcSpriteLayerP)
- {
- SpritePtr curSpriteP;
-
- SW_ASSERT(srcSpriteLayerP != NULL);
-
- while ((curSpriteP = SWGetNextSprite(srcSpriteLayerP, NULL)) != NULL)
- {
- SWRemoveSprite(curSpriteP);
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWDisposeAllSpritesInLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWDisposeAllSpritesInLayer(
- SpriteLayerPtr spriteLayerP)
- {
- SpritePtr curSpriteP, nextSpriteP;
-
- SW_ASSERT(spriteLayerP != NULL);
-
- curSpriteP = spriteLayerP->headSpriteP;
-
- // iterate through the sprites in this layer
- while (curSpriteP != NULL)
- {
- nextSpriteP = curSpriteP->nextSpriteP;
-
- SWRemoveSprite(curSpriteP);
- SWDisposeSprite(&curSpriteP);
-
- curSpriteP = nextSpriteP;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWCountNumSpritesInLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC short SWCountNumSpritesInLayer(
- SpriteLayerPtr spriteLayerP)
- {
- SpritePtr curSpriteP;
- short numSprites = 0;
-
- SW_ASSERT(spriteLayerP != NULL);
-
- curSpriteP = spriteLayerP->headSpriteP;
-
- // iterate through the sprites in this layer
- while (curSpriteP != NULL)
- {
- numSprites++;
- curSpriteP = curSpriteP->nextSpriteP;
- }
-
- return numSprites;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWSwapSprite
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC OSErr SWSwapSprite(
- SpritePtr srcSpriteP,
- SpritePtr dstSpriteP)
- {
- SpriteLayerPtr spriteLayerP;
- register SpritePtr swapSpriteP;
- OSErr err = noErr;
-
- SW_ASSERT(srcSpriteP != NULL && dstSpriteP != NULL);
-
- spriteLayerP = srcSpriteP->parentSpriteLayerP;
- if (spriteLayerP != dstSpriteP->parentSpriteLayerP || spriteLayerP == NULL)
- {
- err = kBadParameterErr;
- SWSetStickyIfError( err );
- return err;
- }
-
- // adjacent Sprites are a special case
-
- if ( srcSpriteP->nextSpriteP == dstSpriteP ||
- dstSpriteP->nextSpriteP == srcSpriteP )
- {
- if ( srcSpriteP->nextSpriteP == dstSpriteP )
- {
- if ( srcSpriteP->prevSpriteP != NULL )
- (srcSpriteP->prevSpriteP)->nextSpriteP = dstSpriteP;
- if ( dstSpriteP->nextSpriteP != NULL )
- (dstSpriteP->nextSpriteP)->prevSpriteP = srcSpriteP;
-
- dstSpriteP->prevSpriteP = srcSpriteP->prevSpriteP;
- srcSpriteP->nextSpriteP = dstSpriteP->nextSpriteP;
-
- dstSpriteP->nextSpriteP = srcSpriteP;
- srcSpriteP->prevSpriteP = dstSpriteP;
- }
- else
- {
- if ( dstSpriteP->prevSpriteP != NULL )
- (dstSpriteP->prevSpriteP)->nextSpriteP = srcSpriteP;
- if ( srcSpriteP->nextSpriteP != NULL )
- (srcSpriteP->nextSpriteP)->prevSpriteP = dstSpriteP;
-
- srcSpriteP->prevSpriteP = dstSpriteP->prevSpriteP;
- dstSpriteP->nextSpriteP = srcSpriteP->nextSpriteP;
-
- srcSpriteP->nextSpriteP = dstSpriteP;
- dstSpriteP->prevSpriteP = srcSpriteP;
- }
- }
- else
- {
- if ( srcSpriteP->prevSpriteP != NULL && dstSpriteP->prevSpriteP != NULL )
- {
- swapSpriteP = (srcSpriteP->prevSpriteP)->nextSpriteP;
- (srcSpriteP->prevSpriteP)->nextSpriteP =
- (dstSpriteP->prevSpriteP)->nextSpriteP;
- (dstSpriteP->prevSpriteP)->nextSpriteP = swapSpriteP;
- }
- if ( srcSpriteP->nextSpriteP != NULL && dstSpriteP->nextSpriteP != NULL )
- {
- swapSpriteP = (srcSpriteP->nextSpriteP)->prevSpriteP;
- (srcSpriteP->nextSpriteP)->prevSpriteP =
- (dstSpriteP->nextSpriteP)->prevSpriteP;
- (dstSpriteP->nextSpriteP)->prevSpriteP = swapSpriteP;
- }
-
- swapSpriteP = srcSpriteP->nextSpriteP;
- srcSpriteP->nextSpriteP = dstSpriteP->nextSpriteP;
- dstSpriteP->nextSpriteP = swapSpriteP;
-
- swapSpriteP = srcSpriteP->prevSpriteP;
- srcSpriteP->prevSpriteP = dstSpriteP->prevSpriteP;
- dstSpriteP->prevSpriteP = swapSpriteP;
- }
-
-
- if (srcSpriteP->nextSpriteP == NULL)
- {
- spriteLayerP->tailSpriteP = srcSpriteP;
- }
- else if (srcSpriteP->prevSpriteP == NULL)
- {
- spriteLayerP->headSpriteP = srcSpriteP;
- }
-
- if (dstSpriteP->nextSpriteP == NULL)
- {
- spriteLayerP->tailSpriteP = dstSpriteP;
- }
- else if (dstSpriteP->prevSpriteP == NULL)
- {
- spriteLayerP->headSpriteP = dstSpriteP;
- }
-
- return noErr;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWInsertSpriteAfterSprite
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC OSErr SWInsertSpriteAfterSprite(
- SpritePtr newSpriteP,
- SpritePtr dstSpriteP)
- {
- SpriteLayerPtr spriteLayerP;
- OSErr err = noErr;
-
- SW_ASSERT(newSpriteP != NULL && dstSpriteP != NULL);
-
- spriteLayerP = dstSpriteP->parentSpriteLayerP;
- if (newSpriteP->parentSpriteLayerP != NULL)
- err = kSpriteAlreadyInLayer;
-
- if (err == noErr)
- {
- if ( dstSpriteP->nextSpriteP != NULL )
- (dstSpriteP->nextSpriteP)->prevSpriteP = newSpriteP;
-
- newSpriteP->nextSpriteP = dstSpriteP->nextSpriteP;
- dstSpriteP->nextSpriteP = newSpriteP;
- newSpriteP->prevSpriteP = dstSpriteP;
-
- if (newSpriteP->nextSpriteP == NULL)
- {
- spriteLayerP->tailSpriteP = newSpriteP;
- }
-
- // mark the sprite to be drawn, in case the sprite changed tile layers
- newSpriteP->needsToBeDrawn = true;
-
- newSpriteP->parentSpriteLayerP = spriteLayerP;
- }
-
- SWSetStickyIfError( err );
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWInsertSpriteBeforeSprite
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC OSErr SWInsertSpriteBeforeSprite(
- SpritePtr newSpriteP,
- SpritePtr dstSpriteP)
- {
- SpriteLayerPtr spriteLayerP;
- OSErr err = noErr;
-
- SW_ASSERT(newSpriteP != NULL && dstSpriteP != NULL);
-
- spriteLayerP = dstSpriteP->parentSpriteLayerP;
- if (newSpriteP->parentSpriteLayerP != NULL)
- err = kSpriteAlreadyInLayer;
-
- if (err == noErr)
- {
- if ( dstSpriteP->prevSpriteP != NULL )
- (dstSpriteP->prevSpriteP)->nextSpriteP = newSpriteP;
-
- newSpriteP->prevSpriteP = dstSpriteP->prevSpriteP;
- dstSpriteP->prevSpriteP = newSpriteP;
- newSpriteP->nextSpriteP = dstSpriteP;
-
- if (newSpriteP->prevSpriteP == NULL)
- {
- spriteLayerP->headSpriteP = newSpriteP;
- }
-
- // mark the sprite to be drawn, in case the sprite changed tile layers
- newSpriteP->needsToBeDrawn = true;
-
- newSpriteP->parentSpriteLayerP = spriteLayerP;
- }
-
- SWSetStickyIfError( err );
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWGetNextSprite
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC SpritePtr SWGetNextSprite(
- SpriteLayerPtr spriteLayerP,
- SpritePtr curSpriteP)
- {
- SW_ASSERT(spriteLayerP != NULL);
-
- return (curSpriteP == NULL) ? spriteLayerP->headSpriteP : curSpriteP->nextSpriteP;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWLockSpriteLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWLockSpriteLayer(
- SpriteLayerPtr spriteLayerP)
- {
- SpritePtr curSpriteP;
-
- SW_ASSERT(spriteLayerP != NULL);
-
- curSpriteP = spriteLayerP->headSpriteP;
-
- while (curSpriteP != NULL)
- {
- SWLockSprite(curSpriteP);
-
- curSpriteP = curSpriteP->nextSpriteP;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWUnlockSpriteLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWUnlockSpriteLayer(
- SpriteLayerPtr spriteLayerP)
- {
- SpritePtr curSpriteP;
-
- SW_ASSERT(spriteLayerP != NULL);
-
- curSpriteP = spriteLayerP->headSpriteP;
-
- while (curSpriteP != NULL)
- {
- SWUnlockSprite(curSpriteP);
-
- curSpriteP = curSpriteP->nextSpriteP;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWCollideSpriteLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWCollideSpriteLayer(
- SpriteWorldPtr spriteWorldP,
- SpriteLayerPtr srcSpriteLayerP,
- SpriteLayerPtr dstSpriteLayerP)
- {
- SpritePtr srcSpriteP, nextSrcSpriteP;
- SpritePtr dstSpriteP, nextDstSpriteP;
- Rect sectRect;
-
- SW_ASSERT(spriteWorldP != NULL);
- SW_ASSERT(srcSpriteLayerP != NULL && dstSpriteLayerP != NULL);
-
- // Don't check for collisions unless the frame has been processed!
- if (!spriteWorldP->frameHasOccurred)
- return;
-
- srcSpriteP = srcSpriteLayerP->headSpriteP;
-
- while (srcSpriteP != NULL)
- {
- dstSpriteP = dstSpriteLayerP->headSpriteP;
- nextSrcSpriteP = srcSpriteP->nextSpriteP;
-
- while (dstSpriteP != NULL)
- {
- nextDstSpriteP = dstSpriteP->nextSpriteP;
-
- if (srcSpriteP != dstSpriteP)
- {
- // are the sprite’s rectangles overlapping?
- if ((srcSpriteP->destFrameRect.top < dstSpriteP->destFrameRect.bottom) &&
- (srcSpriteP->destFrameRect.bottom > dstSpriteP->destFrameRect.top) &&
- (srcSpriteP->destFrameRect.left < dstSpriteP->destFrameRect.right) &&
- (srcSpriteP->destFrameRect.right > dstSpriteP->destFrameRect.left))
- {
- // call the source sprite’s collision routine
- if (srcSpriteP->spriteCollideProc != NULL)
- {
- sectRect.left =
- SW_MAX(srcSpriteP->destFrameRect.left, dstSpriteP->destFrameRect.left);
- sectRect.top =
- SW_MAX(srcSpriteP->destFrameRect.top, dstSpriteP->destFrameRect.top);
- sectRect.right =
- SW_MIN(srcSpriteP->destFrameRect.right, dstSpriteP->destFrameRect.right);
- sectRect.bottom =
- SW_MIN(srcSpriteP->destFrameRect.bottom, dstSpriteP->destFrameRect.bottom);
-
- (*srcSpriteP->spriteCollideProc)(srcSpriteP, dstSpriteP, §Rect);
- }
- }
- }
-
- // If the nextDstSpriteP has been removed, we must start over again
- if (nextDstSpriteP != NULL && nextDstSpriteP->spriteRemoval != kSWDontRemoveSprite)
- dstSpriteP = dstSpriteLayerP->headSpriteP;
- else
- dstSpriteP = nextDstSpriteP;
- }
-
- // If the nextSrcSpriteP has been removed, we must start over again
- if (nextSrcSpriteP != NULL && nextSrcSpriteP->spriteRemoval != kSWDontRemoveSprite)
- srcSpriteP = srcSpriteLayerP->headSpriteP;
- else
- srcSpriteP = nextSrcSpriteP;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWPauseSpriteLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWPauseSpriteLayer(
- SpriteLayerPtr spriteLayerP)
- {
- SW_ASSERT(spriteLayerP != NULL);
-
- spriteLayerP->isPaused = true;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWUnpauseSpriteLayer
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWUnpauseSpriteLayer(
- SpriteLayerPtr spriteLayerP)
- {
- SW_ASSERT(spriteLayerP != NULL);
-
- spriteLayerP->isPaused = false;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWFindSpriteByPoint
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC SpritePtr SWFindSpriteByPoint(
- SpriteLayerPtr spriteLayerP,
- SpritePtr startSpriteP,
- Point testPoint)
- {
- SpritePtr curSpriteP;
-
- SW_ASSERT(spriteLayerP != NULL);
-
- curSpriteP = (startSpriteP == NULL) ? spriteLayerP->tailSpriteP : startSpriteP;
-
- // note that we traverse the sprites in reverse order
- // since this will make the most sense if we are
- // looking for a sprite that was clicked
- while ((curSpriteP != NULL) && !SWIsPointInSprite(curSpriteP, testPoint))
- {
- curSpriteP = curSpriteP->prevSpriteP;
- }
-
- return curSpriteP;
- }
-